'''
    关键字驱动类的实现：
        1. 实现对常用请求的方法封装
        2. 解决在模拟请求的时候的所有内容
        3. 解决断言校验的数据处理，包括数据关联的提取能力。
    封装的设计逻辑：
        1. 对于可有可无的参数，我们优先通过设定默认值为None来确保逻辑的顺利执行
        2. 所有的请求其实都是通过request()方法来实现执行的。
'''

import requests
import jsonpath
from requests import request

from interface_frame.conf.set_conf import read_conf


class ApiKeys:

    # 构造方法：初始化测试环境数据，实现一键切换测试环境。
    def __init__(self):
        self.env = None  # 默认env属性

    # 环境切换方法，用于设置api所处不同的环境。进行测试环境的切换
    def set_env(self, env):
        self.env = env

    # get请求
    # def do_get(self, url, params=None, headers=None, **kwargs):
    #     return requests.get(url=url, params=params, headers=headers, **kwargs)
    #
    # # post请求
    # def do_post(self, url, data=None, json=None, headers=None, **kwargs):
    #     return requests.post(url=url, data=data, json=json, headers=headers, **kwargs)

    # 基于request统一封装的模拟请求。
    def request(self, method, path=None, headers=None, **kwargs):
        '''
        :param method: 请求方法的定义
        :param url: 在不同环境下，url的IP和端口是会有改变，但是接口路径是不会发生变化的。
            基于此特性，我们可以拆解url，进行相关的配置读取操作。从而满足不同环境下的接口测试
        :param headers: 需要新增的请求头参数，基于set_headers方法实现对请求时，请求头信息
            的补全操作
        :param kwargs: 其他请求参数的定义
        :return: 返回response 对象。
        '''
        url = self.set_url(path)
        headers = self.set_headers(headers)
        return request(method=method, url=url, headers=headers, **kwargs)

    # url的拼接处理
    def set_url(self, path):
        url = read_conf(self.env, 'host')
        if path:
            url = url + path
        return url

    # 拼接headers，实现对实时新增的数据进行添加
    def set_headers(self, headers):
        # 定义默认请求头
        base_headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                          'AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/135.0.0.0 Safari/537.36'  # 定义请求的浏览器信息
        }
        if headers:
            base_headers.update(headers)  # 基于headers字典数据添加至base_headers之中。
        # 如果运行过程中，token值已被成功写入，则每次请求都默认拼接token值
        if read_conf('data', 'token'):
            token = read_conf('data', 'token')
            base_headers['Authorization'] = token
        return base_headers

    # jsonpath的封装，获取指定的数据
    def get_text(self, res, key):
        # jsonpath会获取所有的value，返回为list
        # values = jsonpath.jsonpath(res, f'$..{key}')
        values = jsonpath.JSONPath(f'$..{key}').parse(res)  # 拼接字符串，实现表达式的完整性
        # jsonpath获取之后的二次处理
        if values:
            if len(values) == 1:  # 如果长度为1，则直接返回对应内容。
                return values[0]
        return values  # 因为除了单个元素之外，都是返回整个values，所以直接外部定义。
    # 断言校验
    def assert_text(self, expected, res, key):
        reality = self.get_text(res, key)
        assert expected == reality, f'''
预期结果为：{expected}
实际结果为：{reality}
断言结果：{expected} != {reality}
'''
